﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace RainDrops
{
    class Sprite
    {
        // Main attributes needed for constructor
        public Texture2D texture;
        protected float scale = 1.0f;
        protected Color colorTint = Color.White;
        protected Vector2 currentPosition = Vector2.Zero;
        protected Rectangle textureSource;

        private Rectangle fullCurrentPosition;
        private Vector2 center;
        private float collisionRadius;
        private float layer = 1.0f;
        protected Vector2 velocity = new Vector2(0, 0);
        protected Rectangle bounds;
        
        // Movement attributes
        private Vector2 startPosition;
        private Vector2 changePosition;
        private Vector2 destinationPosition;
        private float tweenDuration;
        private double velocityScaling;
        string motionType;
        private bool movement = false;
        private bool animationDone = false;
        private float seconds;
        
        #region Constructors
        public Sprite(Vector2 position, Texture2D texture)
        {
            this.currentPosition = position;
            this.texture = texture;
            this.textureSource = new Rectangle(0, 0, texture.Width, texture.Height);
            this.collisionRadius = texture.Width * scale;
            this.bounds = new Rectangle(0, 0, 800, 480);
        }

        // Needed: position, texture, textureSource, color, scale
        public Sprite(Vector2 position, Texture2D texture, Rectangle textureSource, Color color, float scale)
        {
            this.currentPosition = position;
            this.texture = texture;
            this.textureSource = textureSource;
            this.colorTint = color;
            this.scale = scale;
            this.collisionRadius = (texture.Width * scale)/2;
            this.bounds = new Rectangle(0, 0, 800, 480);
        }

        ~Sprite()
        {
            // System.Diagnostics.Trace.WriteLine("First's destructor is called.");
        }

        public Sprite(Vector2 position, Texture2D texture, Rectangle textureSource, Vector2 velocity, float scale, float layer, Color color)
        {
            // Currently under Developerment, do not use this constructor overload
        }
        #endregion

        public Vector2 CurrentPosition
        {
            get { return currentPosition; }
            set { currentPosition = value; }
        }

        public Rectangle FullCurrentPosition
        {
            get
            {
                return  new Rectangle((int)currentPosition.X, (int)currentPosition.Y, (int)textureSource.Width, (int)textureSource.Height);
            }
            set { fullCurrentPosition = value; }
        }

        public Vector2 Velocity
        {
            get { return velocity; }
            set { if ((value.X < 500) || (value.Y < 500)) { velocity = value; } }
        }

        public virtual float Scale
        {
            get { return scale; }
            set { scale = value; }
        }

        public Vector2 Center
        {
            get { return currentPosition + new Vector2(textureSource.Width / 2, textureSource.Height / 2); }
        }

        public float CollisionRadius
        {
            get { return collisionRadius; }
            set { collisionRadius = value;}
        }

        public void SetNewCollisionRadius()
        {
            CollisionRadius = (texture.Width * scale) / 2;
        }

        public bool IsCircleColliding(Vector2 otherCenter, float otherRadius)
        {
            if (Vector2.Distance(Center, otherCenter) < (CollisionRadius + otherRadius))
                return true;
            else
                return false;
        }

        public bool Movement
        {
            get { return movement; }
            set { movement = value; }
        }

        public bool AnimationDone
        {
            get { return animationDone; }
        }

        public bool onScreen(Sprite sprite)
        {
            if (sprite.FullCurrentPosition.Intersects(bounds))
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        // function to start a tween motion
        public void Tween(string type, Vector2 start, Vector2 end, float duration)
        {
            this.motionType = type;
            this.startPosition = start;
            this.destinationPosition = end;
            this.changePosition = destinationPosition - startPosition;
            this.tweenDuration = duration;
            this.Movement = true;
        }

        public Vector2 TweenEquations(string type,float time, Vector2 start, Vector2 change, float duration)
        {
            switch(type)
            {
                case "linear":
                    return change*time/duration + start;
                case "quadEaseIn":
                    return change*(time/=duration)*time + start;
                case "quadEaseOut":
                    return -change*(time/=duration)*(time-2)+start;
                default:
                    return new Vector2(0, 0);
            }
        }

        // function to start a velocity managed motion
        public void VelocityMotion(Vector2 start, Vector2 end, Vector2 velocity, float scaling)
        {
            this.motionType = "velocity";
            this.startPosition = start;
            this.destinationPosition = end;
            this.velocity = velocity;
            this.velocityScaling = scaling;
            this.Movement = true;
        }

        public Vector2 VelocityEquation(double time, Vector2 start, Vector2 velocity, double scaling)
        {
            return velocity * (float)(Math.Pow(time, scaling)) + start;
        }

    
        public virtual void Update(GameTime gameTime)
        {
            if (movement == true)
            {
                seconds += 0.033f;
                if (motionType == "velocity")
                {
                    // if ((currentPosition.X <= destinationPosition.X) || (currentPosition.Y <= destinationPosition.Y))
                    if (currentPosition.Y <= destinationPosition.Y)
                    {
                        currentPosition = VelocityEquation((double)seconds, startPosition, velocity, velocityScaling);
                    }
                    else { this.Movement = false; this.animationDone = true; }
                }
                else
                {
                    if (seconds <= tweenDuration)
                    {
                        currentPosition = TweenEquations(motionType, seconds, startPosition, changePosition, tweenDuration);
                    }
                    else { this.Movement = false; };
                }
            }
            else
            {
                seconds = 0;
            }
        }

        public virtual void Draw(SpriteBatch spriteBatch)
        {
            //SpriteBatch.Draw (texture, position, origin from texture, color, rotation, rotation origin, scale, spriteeffects, layer)
            spriteBatch.Draw(texture, currentPosition, textureSource, colorTint, 0.0f, Vector2.Zero, scale, SpriteEffects.None, layer);
        }

    }
}
